﻿#include "eventbase.hpp"
#include "iniconfig.hpp"
#include "ipaddress.hpp"
#include "signalhandler.hpp"
#include "singleton.hpp"
#include "sock5server.hpp"
#include <csignal>
#include <cstdio>
using namespace std;
using namespace oraysock5;

/**
 * @brief 默认系统信号处理
 * @param base 反应器
 * @param signum 系统信号
*/
inline void default_sigcb(std::shared_ptr<EventBase> base, int signum)
{
    if (signum == SIGINT) {
        struct timeval delay = { 2, 0 };
        LOG_INFO << "捕获到中断信号,程序将在2秒后安全退出";
        base->loopexit(&delay);
    } else if (signum == SIGQUIT) {
        LOG_INFO << "捕获到退出信号,程序将在立刻安全退出";
        base->loopexit();
    }
}

int main()
{
    try {
        const char* node = "sock5";
        const char* inifile = "sock5.ini";
        IniConfig& ini = Singleton<IniConfig>::instance(inifile);
        bool d = ini.get<bool>(node, "daemon");
        if (d) {
            daemon();
        }
        Logger::set_loglevel(Logger::LogLevel::DEBUG);
        Logger::set_logname(node);
        string ip = ini.get<string>(node, "ip");
        short port = ini.get<short>(node, "port");

        const char* pid_dir = "./pid/";
        mkdir_recursive(pid_dir);
        std::string pidfile = str_format("./%s/%s.pid", pid_dir, node);
        writepid(pidfile.c_str());

        shared_ptr<EventBase> base(new EventBase());

        shared_ptr<IPAddress> ipaddr = make_shared<IPAddress>(ip.c_str(), port);
        shared_ptr<Sock5Server> sock5server = make_shared<Sock5Server>(ipaddr);
        sock5server->set_event(base, sock5server->listenfd(), EV_READ | EV_PERSIST);
        base->addevent(sock5server, nullptr);

        SignalHandler* sigmgr = &Singleton<SignalHandler>::instance();
        sigmgr->add(base, SIGINT, default_sigcb);
        sigmgr->add(base, SIGQUIT, default_sigcb);
        base->dispatch();

    } catch (const std::exception& err) {
        print_exception(err);
    }
    EventBase::event_shutdown();
    return 0;
}
